﻿using Newtonsoft.Json;
using System;
using System.Linq;
using System.Security.Cryptography;
using System.Text;
using System.Web.Caching;
using System.Web.Mvc;

namespace Yz.Mvc.Filters
{
    [AttributeUsage(AttributeTargets.Method | AttributeTargets.Class, AllowMultiple = true)]
    public class PreventSpamAttribute : ActionFilterAttribute
    {
        /// <summary>
        ///     处理请求之间的延迟时间（单位：秒）
        /// </summary>
        public int DelayRequest = 1;

        //防止多次请求时的错误提示信息
        public string ErrorMessage = "您点击的太快了！";

        //出错时URL重定向
        public string RedirectURL;

        //处理请求之间的延迟
        public override void OnActionExecuting(ActionExecutingContext filterContext)
        {
            //存储 HttpContext
            var request = filterContext.HttpContext.Request;
            //存储 HttpContext.Cache
            var cache = filterContext.HttpContext.Cache;

            //获取IP请求者的IP地址
            var originationInfo = request.ServerVariables["HTTP_X_FORWARDED_FOR"] ?? request.UserHostAddress;

            //Append the User Agent
            originationInfo += request.UserAgent;

            //目标URL信息
            var targetInfo = request.RawUrl + request.QueryString;
            var paras = JsonConvert.SerializeObject(request.Params);
            //创建希哈值
            var hashValue = string.Join("",
                MD5.Create().ComputeHash(Encoding.ASCII.GetBytes(originationInfo + targetInfo + paras))
                    .Select(s => s.ToString("x2")));

            //如果希哈值在缓存中,(重复提交)
            if (cache[hashValue] != null)
            {
                //添加错误信息
                //filterContext.Controller.ViewData.ModelState.AddModelError("ExcessiveRequests", ErrorMessage);
                cache.Add(hashValue, hashValue, null, DateTime.Now.AddSeconds(DelayRequest), System.Web.Caching.Cache.NoSlidingExpiration,
                    CacheItemPriority.Default, null);
                filterContext.Result = new JsonResult
                {
                    Data = new { res = false, msg = ErrorMessage }
                };
            }
            else
            {
                //使用希哈值的key添加一个空对象到缓存中(决定是否过期)
                //if the Request is valid or not
                cache.Add(hashValue, hashValue, null, DateTime.Now.AddSeconds(DelayRequest), System.Web.Caching.Cache.NoSlidingExpiration,
                    CacheItemPriority.Default, null);
            }

            base.OnActionExecuting(filterContext);
        }
    }
}